Datasync между браузерами
При постройке качественного single-page приложения рано или поздно встаёт вопрос синхронизации данных. Это тем более актуально, когда дело касается работы разных пользователей. Приложения типа google wave, google docs, push-notifications в IOS, подняли планку ожидания пользователей и от обычных веб-систем
Что даёт синхронизация
Увеличивает реактивность, поддерживая данные в реальном времени без обновления страницы. Типичная ситуация когда вы работаете в нескольких табах и данные не обновляются потому что закешировались
Улучшает безопасность — если пользователь выходит из одного таба, его можно выкинуть из остальных автоматически
Снижает нагрузку на сервер — можно высылать оповещение о состоянии файла, если он обрабатывается в реальном времени, подобно ютубу без какого-либо взаимодействия с пользователем или поллинга
Сложности реализации
Если вы решили что это must-have фича, прежде чем начать реализовывать её у себя, задумайтесь о последствиях:
- Вам понадобится транспортный механизм (см. ниже), который обычно ограничен количеством подключённых пользователей (макс. 10 тыс), размером сообщения и объёмом траффика
- Безопасность. Транспортный механизм и источник оповещения должен точечно высылать дан ные только нужному пользователю (без broadcast-а).
Лучше всего источник оповещения ставить на backend, сразу после закрытия транзакции. В этом случае полезно привязываться к сессии на бэкэнде - Я советую не использовать datasync-сервис в качестве источника данных. Это должен быть легковесный вестник адреса по которому можно прочитать детали. Более того, формат этого сообщения должен быть стандартизирован. Например
{action:'file.added', id:1345}
- Весь front-end код должен хранить данные в сыром виде в сервисах/моделях, которые будут точечно обновляться.
Соответсвенно все события будут делится на прямое вмешательство пользователя и на datasync-действия
Код при этом будет запускать похожие функции над данными - Все use-кейсы усложняются из-за ситуаций
- что делать если A удалил данные который B просматривает (редиректить B, блокировать A, показывать оповещение B?)
- что делать если A и B одновременно сохраняют изменения над одним и тем же обьектом (провести обе операции, кто последний тот и победил? провести первую и заблокировать последующие до окончания операции?)
- что делать если A составляет новый обьект 3, ссылающийся на обьект 2, который удаляет B, а потом происходит сохранение (удалять include при удалении или при сохранении?)
- Если вы используете систему привилегий, то надо дополнительно иметь оповещения о присвоении или изъятия обьекта из видимости пользователей
- Если ваш сервис синхронизации вдруг упадёт, то при поднимании надо сделать так что-бы сообщения не потерялись из-за ещё неподключившихся пользователей (у socket.io 5 сек)
Polling
Не ушёл в небытие, я по-прежнему вижу как некоторые сайты настойчиво стучат в бэкэнд. Например движение общественного транспорта в Таллинне. Видимо это проще всего реализовать и проще всего использовать вместо API. Что может быть проще для сторонних разработчиков - просто читай .json файл так часто как тебе это надо. А он в свою очередь может выплёвываться из кэша-в-памяти
Pusher
Пушер — сервис который вобщем- то следующий по сложности для разработчиков. Внедряете скрипт, подписываетесь на события в js. Высылаете события, которые будут получать все пользователи.
Лучше всего это делать на уровне backend'а, иначе захламите frontend и могут возникнуть редкие баги. Например — поставил заливаться файл и закрыл браузер, а клиент X не получил итогового оповещения. Для более тонкой настройки прийдётся повозиться с интеграцией авторизации и токенами
Firebase
Наконец, ещё один сервис, купленный гуглом, который больше позиционируется как nosql-база данных с синхронизацией между клиентами. Для того что-бы настроить её, как систему оповещений, но при этом оставить хран ение данных у себя, прийдётся повозиться. Изначальный setup такой же простой как у pusher'а, да и авторизация по токену такая же, но поскольку это БД, то подписываться надо не на события оповещений, а на изменения json-схемы. Саму json-схему вы делаете сами, но я советую для этого случая использовать что-то типа..
{
notifications:[
2345:[
'file X added by 2346',
'file Y deleted by 2346'
],
2346:[
'file X added by 2345'
]
]
}
Websocket-сервер / Socket.io
Socket.io вы должны хостить сами и для этого нужен nodejs. Socket.io реализует браузерные веб-сокеты, протокол которых менялся несколько раз. Из-за этого могут быть трудности с подключением со стороны php к нему. Я использую elephant.io, пока полёт нормальный. Самый простой начальный вариант — socket.io принимает подключение и делает broadcast всем подключённым клиентам. Для более тонкой настройки прийдётся повозиться с куки, php сессиями и желательно переносом их хранения в БД, что-бы backend мог высылать безопасно сообщение конкретному подключённому пользователю, после чего контролировать по session_id + socket кто что будет получать.
У socket.io есть альтернативные библиотечки — socky (любит руби), sockJs, вроде как очень быстрый ws, engine.io, data.io. Faye я сам не пробовал, но судя по описанию растёт ещё со времени когда терминология с кометами была на слуху. Видимо теперь тоже работает на веб-сокетах